package com.spzx.product.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.common.redis.util.RedisLockUtilV1;
import com.spzx.product.domain.ProductSku;
import com.spzx.product.domain.SkuPriceDTO;
import com.spzx.product.domain.SkuStockDTO;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.ProductSkuService;
import com.spzx.product.mapper.ProductSkuMapper;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.IllegalFormatCodePointException;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
* @author 老韦
* @description 针对表【product_sku(商品sku)】的数据库操作Service实现
* @createDate 2024-09-24 14:07:17
*/
@Service
public class ProductSkuServiceImpl extends ServiceImpl<ProductSkuMapper, ProductSku>
    implements ProductSkuService{

    @Resource
    SkuStockMapper skuStockMapper;
    @Resource
    RedisTemplate redisTemplate;
/*
    @Override
    public List<SkuPriceDTO> checkSkusPrice(List<SkuPriceDTO> skuPriceDTOS) {
        if(CollectionUtils.isEmpty(skuPriceDTOS)){
            return null;
        }
        skuPriceDTOS.forEach(skuPriceDTO -> {
            ProductSku sku = this.getById(skuPriceDTO.getSkuId());
            //使用商品的销售价格 和 订单项的购买价格 进行比较
            if(skuPriceDTO.getSkuPrice().compareTo(sku.getSalePrice()) == 0){
                //表示价格一样:验价通过
                skuPriceDTO.setFlag(true);
            }

        });

        //如果价格有变动的，skuPriceDTO的flag为false
        // 需要同步购物车中的商品价格
        //TODO： rabbitmq实现价格同步

        return skuPriceDTOS;
    }

    //验库存锁库存业务
    @Override
    public List<SkuStockDTO> checkSkusStock(List<SkuStockDTO> skuStockDTOs) {
        if(CollectionUtils.isEmpty(skuStockDTOs)){
            return null;
        }
        //遍历每个要验库存的dto对象
        checkAndLockStock(skuStockDTOs);
        //判断 如果有锁定失败的库存，要释放所有库存
        //1、获取锁定成功的库存列表
        List<SkuStockDTO> lockSuccessStockDTOS =
                skuStockDTOs.stream().filter(skuStockDTO -> skuStockDTO.getFlag()).collect(Collectors.toList());
        //2、判断是否有失败的
        if(lockSuccessStockDTOS.size() != skuStockDTOs.size()){
            //有失败的，释放锁定成功的库存
            lockSuccessStockDTOS.forEach(skuStockDTO -> {
                skuStockMapper.releaseStock(skuStockDTO.getSkuId() , skuStockDTO.getSkuNum());
            });
        }
        //TODO 3、如果全部锁定库存成功： 需要将锁定的数据缓存，以便关单/取消订单时 释放库存
        return skuStockDTOs;
    }

    private void checkAndLockStock(List<SkuStockDTO> skuStockDTOs) {
        skuStockDTOs.forEach(skuStockDTO -> {
            String uuid = UUID.randomUUID().toString();
            //加分布式锁：
            RedisLockUtilV1.lock("spzx:sku:lock:stock:"+skuStockDTO.getSkuId(),uuid
                    ,10);
            try {
                //查询验证库存并更新库存  available_num  lock_num
                //update sku_stock set available_num = available_num -1 , lock_num = lock_num+1
                // where sku_id = id and available_num - 1 >=0 and del_flag = 0;
                boolean flag = skuStockMapper.checkAndLockStock(skuStockDTO.getSkuId() , skuStockDTO.getSkuNum());
                skuStockDTO.setFlag(flag);

                if(!flag){
                    //锁库存失败，后续业务不再执行
                    return;//结束checkAndLockStock方法
                }
            } finally {
                //释放分布式锁：
                RedisLockUtilV1.releaseLock("spzx:sku:lock:stock:"+skuStockDTO.getSkuId(),uuid);
            }
        });
    }*/
    @Override
    public List<SkuStockDTO> checkSkusStock(List<SkuStockDTO> skuStockDTOs) {
        if(CollectionUtils.isEmpty(skuStockDTOs)){
            return null;
        }
        //遍历每个要验库存的dto对象
        checkAndLockStock(skuStockDTOs);
        //判断 如果有锁定失败的库存，要释放所有库存
        //1、获取锁定成功的库存列表
        List<SkuStockDTO> lockSuccessStockDTOS =
                skuStockDTOs.stream().filter(skuStockDTO -> skuStockDTO.getFlag()).collect(Collectors.toList());
        //2、判断是否有失败的
        if(lockSuccessStockDTOS.size() != skuStockDTOs.size()){
            //有失败的，释放锁定成功的库存
            lockSuccessStockDTOS.forEach(skuStockDTO -> {
                skuStockMapper.releaseStock(skuStockDTO.getSkuId() , skuStockDTO.getSkuNum());
            });
        }else {
            // 3、如果全部锁定库存成功： 需要将锁定的数据缓存，以便关单/取消订单时 释放库存
            String orderNo = lockSuccessStockDTOS.get(0).getOrderNo();
            redisTemplate.opsForValue().set("spzx:product:stock:"+orderNo,lockSuccessStockDTOS);

        }


        return skuStockDTOs;

    }

    @Override
    public List<SkuPriceDTO> checkSkusPrice(List<SkuPriceDTO> skuPriceDTOS) {

        if (CollectionUtils.isEmpty(skuPriceDTOS)){
            return null;
        }
        skuPriceDTOS.forEach(skuPriceDTO -> {
            ProductSku sku = this.getById(skuPriceDTO.getSkuId());
            //使用商品的销售价格 和 订单项的购买价格 进行比较
            if (skuPriceDTO.getSkuPrice().compareTo(sku.getSalePrice()) == 0) {
                //表示价格一样:验价通过
                skuPriceDTO.setFlag(true);
            }
        });


        //如果价格有变动的，skuPriceDTO的flag为false
        // 需要同步购物车中的商品价格
        //TODO： rabbitmq实现价格同步
        return skuPriceDTOS;

    }

    private void checkAndLockStock(List<SkuStockDTO> skuStockDTOs) {
        String uuid = UUID.randomUUID().toString();

        skuStockDTOs.forEach(skuStockDTO -> {
            RedisLockUtilV1.lock("spzx:sku:lock:stock:"+skuStockDTO.getSkuId(),uuid,10);
        try {

            //查询验证库存 更新库存  available_num  lock_num
            boolean flag =   skuStockMapper.checkAndLockStock(skuStockDTO.getSkuId(),skuStockDTO.getSkuNum());
            skuStockDTO.setFlag(flag);
            if (!flag){
                //锁库存失败，后续业务不再执行
                return;
            }


        }finally {
            //释放锁
            RedisLockUtilV1.releaseLock("spzx:sku:lock:stock:"+skuStockDTO.getSkuId(),uuid);

        }

        });


    }
}




